In [46]:
import ipynb.fs.full.features as features
In [47]:
from sklearn import preprocessing
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin_min

%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
plt.rcParams['figure.figsize'] = (16, 9)
plt.style.use('ggplot')

df_train = pd.read_csv('./data/train.csv')
df_aux_train = df_train

df_test = pd.read_csv('./data/test.csv')
df_aux_test = df_test
In [48]:
# Normalizacion

def _normalizacion(df, columnas):
    x = df.values #returns a numpy array
    min_max_scaler = preprocessing.MinMaxScaler()
    x_scaled = min_max_scaler.fit_transform(x)
    df = pd.DataFrame(x_scaled)
    df.columns = columnas
    return df
In [49]:
def generar_grafico(df_completo, columnas, df_y=[]):
    """ df_completo: El df a calcular kmeans
        columnas: Es con que columnas se va a calcular
        df_y es la columna precio (es una serie)"""
    """Muestra el grafico de variacion entre 0 y 20 clusters(k)"""
    """Retorna X e y, para usar en el entrenamiento y la clasificacion"""
    df = df_completo[columnas].copy()
    for columna in columnas:
        df[columna] = df[columna].fillna(df[columna].mean())
    df = _normalizacion(df, columnas)
    
    X = np.array(df[columnas])
    y = None if type(df_y) == list else np.array(df_y)
    
    Nc = range(1, 20)
    kmeans = [KMeans(n_clusters=i) for i in Nc]
    score = [kmeans[i].fit(X).score(X) for i in range(len(kmeans))]

    plt.figure(figsize=(15,15))
    plt.plot(Nc,score)
    plt.xlabel('Number of Clusters')
    plt.ylabel('Score')
    plt.title('Elbow Curve')
    plt.show()
    
    return df, X, y
In [50]:
def etiquetado(k_cluster, X):
    # k Max es el largo de este arreglo
    colores=['red','green','blue','cyan','yellow', 'black', 'brown', 'orange', 'pink', 'purple', 'beige']
    kmeans = KMeans(n_clusters=k_cluster).fit(X)
    colores = colores[:k_cluster]
    # Clasificacion
    labels = kmeans.predict(X)
    C = kmeans.cluster_centers_ # Centroides
    asignar = []
    for row in labels:
        asignar.append(colores[row])
    # Grafico de todos los puntos clasificados:    
    if X.shape[1] > 2:
        fig = plt.figure(figsize=(20,20))
        ax = Axes3D(fig)
        ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=asignar,s=60)
        ax.scatter(C[:, 0], C[:, 1], C[:, 2], marker='*', c=colores, s=1000)
    return labels, asignar, X, C, colores
In [51]:
def proyeccion_2d(df, col1, col2, asignar, C, colores, fig_size=(20, 20)):
    f1 = df[col1].values
    f2 = df[col2].values

    plt.figure(figsize=fig_size)
    plt.scatter(f1, f2, c=asignar, s=70)
    plt.scatter(C[:, 0], C[:, 1], marker='*', c=colores, s=1000)
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.show()
In [52]:
def generar_csv_final(ids_series, labels, colores):
    final =  pd.DataFrame()
    # final['id'] = df_aux['id'].values
    final['id'] = ids_series.values
    final['label'] = labels;
    cantidadGrupo =  pd.DataFrame()
    cantidadGrupo['color'] = colores
    cantidadGrupo['cantidad'] = final.groupby('label').size()
    display(cantidadGrupo)
    return final

Features Básicos

Con el set de entrenamiento

In [53]:
columnas_basicas = ['metroscubiertos', 'metrostotales', 'antiguedad', 'habitaciones', 'garages', 'banos',
            'lat', 'lng', 'escuelascercanas', 'centroscomercialescercanos']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_basicas, df_precio)
In [54]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [55]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [56]:
proyeccion_2d(df_train, 'antiguedad', 'metrostotales', asignar, C, colores)
In [57]:
ids_series = df_aux_train['id']
final_train_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_basicas = final_train_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 18679
1 green 74129
2 blue 52403
3 cyan 52024
4 yellow 7253
5 black 35512

Con el set de testeo

In [58]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_basicas)
In [59]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [60]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [61]:
proyeccion_2d(df_test, 'antiguedad', 'metrostotales', asignar, C, colores)
In [62]:
ids_series = df_aux_test['id']
final_test_columnas_basicas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_basicas = final_test_columnas_basicas.rename(columns={'label':'kmeans_basicos'})
color cantidad
0 red 13220
1 green 1823
2 blue 4655
3 cyan 18199
4 yellow 8890
5 black 13213

Features Dependientes de la superficie

Set de entrenamiento

In [63]:
columnas_superficie = ['metroscubiertos', 'metrostotales']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_superficie, df_precio)
In [64]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [65]:
proyeccion_2d(df_train, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [66]:
ids_series = df_aux_train['id']
final_train_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_train_columnas_superficie = final_train_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 31914
1 green 14963
2 blue 34587
3 cyan 39481
4 yellow 17900
5 black 48755
6 brown 16102
7 orange 36298

Set de testeo

In [67]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_superficie)
In [68]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [69]:
proyeccion_2d(df_test, 'metroscubiertos', 'metrostotales', asignar, C, colores)
In [70]:
ids_series = df_aux_test['id']
final_test_columnas_superficie = generar_csv_final(ids_series, labels, colores)
final_test_columnas_superficie = final_test_columnas_superficie.rename(columns={'label':'kmeans_superficie'})
color cantidad
0 red 8586
1 green 3780
2 blue 4443
3 cyan 12053
4 yellow 4036
5 black 7902
6 brown 9255
7 orange 9945

Features por metros totales cubiertos

Set de Entrenamiento

In [71]:
def metros_totales_cubiertos(df):
    punto20 = df_train['metrostotales'].quantile(0.2)
    punto40 = df_train['metrostotales'].quantile(0.4)
    punto60 = df_train['metrostotales'].quantile(0.6)
    punto80 = df_train['metrostotales'].quantile(0.8)
    punto20_cubiertos = df_train['metroscubiertos'].quantile(0.2)
    punto40_cubiertos = df_train['metroscubiertos'].quantile(0.4)
    punto60_cubiertos = df_train['metroscubiertos'].quantile(0.6)
    punto80_cubiertos = df_train['metroscubiertos'].quantile(0.8)
    df['metrostotales'] = df['metrostotales'].fillna(df['metroscubiertos'])
    df['metroscubiertos'] = df['metroscubiertos'].fillna(df['metrostotales'])
    df['metrostotales_log'] = np.log(df['metrostotales'])
    df['metroscubiertos_log'] = np.log(df['metroscubiertos'])
    df['porcentaje_metros'] = df['metroscubiertos']/df['metrostotales']
    df['diferencia_metros'] = df['metrostotales'] - df['metroscubiertos']
    df['intervalo_metros_totales'] = features.map_values(df['metrostotales'].values, lambda x: 1 if x<punto20 else (2 if punto20<x<punto40 else (3 if punto40<x<punto60 else(4 if punto60<x<punto80 else 5))))
    df['intervalo_metros_cubiertos'] = features.map_values(df['metroscubiertos'].values, lambda x: 1 if x<punto20_cubiertos else (2 if punto20_cubiertos<x<punto40_cubiertos else (3 if punto40_cubiertos<x<punto60_cubiertos else(4 if punto60_cubiertos<x<punto80_cubiertos else 5))))
    df['metroscubiertos_bins_unif'] = features.generar_intervalos_unif(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_perc'] = features.generar_intervalos_perc(df, 10, 'metroscubiertos')
    df['metroscubiertos_bins_unif'] = df['metroscubiertos_bins_unif'].astype(int)
    df['metroscubiertos_bins_perc'] = df['metroscubiertos_bins_perc'].astype(int)
    return df
In [72]:
df = df_aux_train.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos, df_precio)
In [73]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [74]:
proyeccion_2d(df_train, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [75]:
ids_series = df['id']
final_train_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_train_columnas_metros_cubiertos = final_train_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 11353
1 green 57236
2 blue 41897
3 cyan 53902
4 yellow 47281
5 black 28331

Set de testeo

In [76]:
df = df_aux_test.copy()
df = metros_totales_cubiertos(df)

columnas_metros_totales_cubiertos = ['metrostotales', 'metroscubiertos', 'metrostotales_log',
                    'metroscubiertos_log', 'porcentaje_metros', 'diferencia_metros', 'intervalo_metros_totales', 
                    'intervalo_metros_cubiertos', 'metroscubiertos_bins_unif', 'metroscubiertos_bins_perc' ]

df_test, X, Y = generar_grafico(df, columnas_metros_totales_cubiertos)
In [77]:
labels, asignar, X, C, colores = etiquetado(6, X)
In [78]:
proyeccion_2d(df_test, 'intervalo_metros_cubiertos', 'diferencia_metros', asignar, C, colores)
In [79]:
ids_series = df['id']
final_test_columnas_metros_cubiertos = generar_csv_final(ids_series, labels, colores)
final_test_columnas_metros_cubiertos = final_test_columnas_metros_cubiertos.rename(columns={'label':'kmeans_metroscubiertos'})
color cantidad
0 red 11926
1 green 10407
2 blue 2875
3 cyan 13294
4 yellow 7092
5 black 14406

Por fecha

Para el set de entrenamiento

In [80]:
def generar_features_fecha(df):
    df['fecha'] = pd.to_datetime(df['fecha'])
    df['anio'] = df['fecha'].dt.year
    df['mes'] = df['fecha'].dt.month
    df['dia'] = df['fecha'].dt.day
    df['trimestre'] = (df['fecha'].dt.month)%3+1
    df['delta_desde_datos'] = (df['fecha'] - df['fecha'].min())
    df['dias_desde_datos'] = df['delta_desde_datos'].dt.days
    df['meses_desde_datos'] = df['dias_desde_datos'] // 30   # Mas o menos...
    df.pop('delta_desde_datos')
    df['fecha'] = df['fecha'].astype(int)
    return df
In [81]:
df = df_aux_train.copy()
df = generar_features_fecha(df)

columnas_por_fecha = ['fecha', 'anio', 'mes', 'dia', 'trimestre', 'dias_desde_datos', 'meses_desde_datos' ]

df_precio = df['precio']
df_train, X, Y = generar_grafico(df, columnas_por_fecha, df_precio)
In [82]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [83]:
proyeccion_2d(df_train, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [84]:
ids_series = df['id']
final_train_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_train_columnas_fechas = final_train_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 18492
1 green 32091
2 blue 22270
3 cyan 24867
4 yellow 21168
5 black 21742
6 brown 18021
7 orange 21558
8 pink 20873
9 purple 18550
10 beige 20368

Para el set de testeo

In [85]:
df = df_aux_test.copy()
df = generar_features_fecha(df)

df_test, X, Y = generar_grafico(df, columnas_por_fecha)
In [86]:
labels, asignar, X, C, colores = etiquetado(11, X)
In [87]:
proyeccion_2d(df_test, 'dias_desde_datos', 'meses_desde_datos', asignar, C, colores)
In [88]:
ids_series = df['id']
final_test_columnas_fechas = generar_csv_final(ids_series, labels, colores)
final_test_columnas_fechas = final_test_columnas_fechas.rename(columns={'label':'kmeans_fechas'})
color cantidad
0 red 3856
1 green 6871
2 blue 5009
3 cyan 5445
4 yellow 4592
5 black 7478
6 brown 7034
7 orange 5718
8 pink 5430
9 purple 3283
10 beige 5284

Features Por latitud y longitud

Set de entrenamiento

In [89]:
columnas_lat_lng = ['lat', 'lng']

df_precio = df_aux_train['precio']
df_train, X, Y = generar_grafico(df_aux_train, columnas_lat_lng, df_precio)
In [90]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [91]:
proyeccion_2d(df_train, 'lat', 'lng', asignar, C, colores)
In [92]:
ids_series = df_aux_train['id']
final_train_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_train_columnas_latlng = final_train_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 137730
1 green 495
2 blue 3502
3 cyan 104
4 yellow 10758
5 black 6256
6 brown 64318
7 orange 16837

Para el set de test

In [93]:
df_test, X, Y = generar_grafico(df_aux_test, columnas_lat_lng)
In [94]:
labels, asignar, X, C, colores = etiquetado(8, X)
In [95]:
proyeccion_2d(df_test, 'lat', 'lng', asignar, C, colores)
In [96]:
ids_series = df_aux_test['id']
final_test_columnas_latlng = generar_csv_final(ids_series, labels, colores)
final_test_columnas_latlng = final_test_columnas_latlng.rename(columns={'label':'kmeans_latlng'})
color cantidad
0 red 34060
1 green 114
2 blue 838
3 cyan 25
4 yellow 2960
5 black 1315
6 brown 16408
7 orange 4280

Juntar todos los features en un solo df

Set de entrenamiento

In [97]:
clustering_train = pd.merge(final_train_columnas_basicas, final_train_columnas_superficie, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_metros_cubiertos, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_fechas, on='id')
clustering_train = pd.merge(clustering_train, final_train_columnas_latlng, on='id')
clustering_train.to_csv('./data/clustering_train_muchos.csv', index=False)
clustering_train
Out[97]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 254099 1 5 4 6 0
1 53461 5 0 2 3 6
2 247984 1 3 3 7 0
3 209067 2 5 4 3 6
4 185997 1 5 1 5 0
... ... ... ... ... ... ...
239995 119879 1 2 4 8 0
239996 259178 5 3 0 1 6
239997 131932 1 7 1 5 0
239998 146867 5 0 2 1 6
239999 121958 1 3 3 5 0

240000 rows × 6 columns

Set de Testeo

In [98]:
clustering_test = pd.merge(final_test_columnas_basicas, final_test_columnas_superficie, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_metros_cubiertos, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_fechas, on='id')
clustering_test = pd.merge(clustering_test, final_test_columnas_latlng, on='id')
clustering_test.to_csv('./data/clustering_test_muchos.csv', index=False)
clustering_test
Out[98]:
id kmeans_basicos kmeans_superficie kmeans_metroscubiertos kmeans_fechas kmeans_latlng
0 4941 0 5 1 0 6
1 51775 3 3 0 1 5
2 115253 1 3 5 1 6
3 299321 3 3 5 8 6
4 173570 5 3 0 9 6
... ... ... ... ... ... ...
59995 75094 4 5 1 5 6
59996 171847 5 3 0 1 0
59997 138313 5 0 5 5 0
59998 271268 5 6 5 1 0
59999 72612 5 6 3 9 7

60000 rows × 6 columns